package redsoxfan.gamejam.base;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;

import javax.swing.JPanel;

/**
 * All games using this base library should extend this class.<br>
 * <br>
 * The following methods are required:
 * <ul>
 * 		<li>public String <a href="#authors()">authors()</a>
 * 		<li>public void <a href="#draw(java.awt.Graphics)">draw(Graphics g)</a>
 * 		<li>public void <a href="#icon()">icon()</a>
 * 		<li>public void <a href="#init()">init()</a>
 * 		<li>public String <a href="#shortTitle()">shortTitle()</a>
 * 		<li>public void <a href="#tick()">tick()</a>
 * 		<li>public String <a href="#title()">title()</a>
 * </ul>
 * 
 * The following methods are optional:
 * <ul>
 * 		<li>public String <a href="#afterApplet()">afterApplet()</a>
 * 		<li>public String <a href="#beforeApplet()">beforeApplet()</a>
 * 		<li>public int <a href="#fps()">fps()</a>
 * 		<li>public int <a href="#fullscreenKey()">fullscreenKey()</a>
 * 		<li>public int <a href="#height()">height()</a>
 * 		<li>public int <a href="#width()">width()</a>
 * </ul>
 * 
 * @author RedSoxFan
 * @since 20 Apr 14
 * @version 1.0
 */
public abstract class Game extends JPanel {
	/**
	 * Image to use for buffering what gets painted
	 */
	private BufferedImage buffer = new BufferedImage(width(), height(), BufferedImage.TYPE_INT_RGB);
	/**
	 * Graphics handle to the screen buffer
	 */
	private Graphics bufferGraphics = buffer.createGraphics();
	/**
	 * Wrapper instance for this game.
	 */
	private GameWrapper wrapper = null;
	/**
	 * HTML to insert after the applet in the AppletWrapper deployment. By default, nothing.
	 * @return HTML to insert after the applet in the AppletWrapper deployment
	 */
	public String afterApplet() {
		return "";
	}
	/**
	 * Author string for the game
	 * @return Author string
	 */
	public abstract String authors();
	/**
	 * HTML to insert before the applet in the AppletWrapper deployment. By default, nothing.
	 * @return HTML to insert before the applet in the AppletWrapper deployment
	 */
	public String beforeApplet() {
		return "";
	}
	/**
	 * Paint the game using this method
	 * @param g - Handle to the screen buffer's graphics handle
	 */
	public abstract void draw(Graphics g);
	/**
	 * Desired FPS for this game. The default is 30.
	 * @return Desired FPS
	 */
	public int fps() {
		return 30;
	}
	/**
	 * Which key should be used to toggle full screen. The default is F11 (KeyEvent.VK_F11)
	 * @return Key used to toggle the full screen state
	 */
	public int fullscreenKey() {
		return KeyEvent.VK_F11;
	}
	/**
	 * Returns the handle to the wrapper
	 * @return The handle to the wrapper
	 */
	public GameWrapper getWrapper() {
		return wrapper;
	}
	/**
	 * What height is used to create the game? The default is 600. The buffer will be created with
	 * this height and it will be stretched on paint
	 * @return Height of the game internals
	 */
	public int height() {
		return 600;
	}
	/**
	 * Icon to use for a window
	 * @return Icon to use for a window
	 */
	public abstract Image icon();
	/**
	 * Generate the info block. This can be placed before the applet.
	 * @param jamURL - URL of the game jam
	 * @param jamName - Name of game jam
	 * @param dateOfComp - Date of the competition (in the format to be displayed)
	 * @param theme - Theme of the jam
	 * @param objective - Objective of the game (HTML formatted)
	 * @param controls - Controls for the game (HTML formatted)
	 * @return Info block HTML snippet
	 */
	public String infoBlock(String jamURL, String jamName, String dateOfComp, String theme, String objective, String controls) {
		return infoBlock(jamURL, jamName, dateOfComp, theme, objective, controls, "", "");
	}
	/**
	 * Generate the info block. This can be placed before the applet.
	 * @param jamURL - URL of the game jam
	 * @param jamName - Name of game jam
	 * @param dateOfComp - Date of the competition (in the format to be displayed)
	 * @param theme - Theme of the jam
	 * @param objective - Objective of the game (HTML formatted)
	 * @param controls - Controls for the game (HTML formatted)
	 * @param repoURL - URL of source code repository (leave blank if none)
	 * @param repoType - Type of source code repository (leave blank if none). For example, SVN or GIT.
	 * @return Info block HTML snippet
	 */
	public String infoBlock(String jamURL, String jamName, String dateOfComp, String theme, String objective,
			String controls, String repoURL, String repoType) {
		String repoTag = repoURL != null && !repoURL.isEmpty() ? "<a href=\""+repoURL+"\" target=\"_blank\">"+repoType+"</a> | " : "";
		String str = "<div style=\"background: #333333; color: #ECECEC; width: 200px; margin-left: 50px; padding: 5px; " +
				"position: absolute; text-align: right\">\n" +
				"	<h4 style=\"text-align: center; margin: 0px\">"+title()+"</h4>\n" +
				"	<h5 style=\"text-align: center; margin: 0px\">By "+authors()+"</h5>\n" +
				"	<br />\n" +
				" 	<img src=\"icon.png\" style=\"width: 100px; height: 100px; display: block; margin-left: auto; margin-right: auto\"/>\n" +
				"	<br />\n" +
				"	<b style=\"float: left\">Jam:</b> <a href=\""+jamURL+"\" target=\"_blank\">"+jamName+"</a><br />\n" +
				"	<b style=\"float: left\">Date:</b> "+dateOfComp+"<br />\n" +
				"	<b style=\"float: left\">Theme:</b> "+theme+"</i><br />\n" +
				"	<b style=\"float: left\">Source:</b> "+repoTag+"<a href=\""+shortTitle()+".zip\">ZIP</a><br />\n" +
				"	<b style=\"float: left\">Binary:</b> <a href=\""+shortTitle()+".jar\">JAR</a><br />\n" +
				"	<br />\n" +
				"	<p style=\"text-align: center; margin: 0px;\">\n" +
				"		<b>Objective</b><br />\n" +
				"			"+objective+"<br />\n"+
				"		<br />\n" +
				"		<b>Controls</b><br />\n" +
				"			"+controls+"<br />\n"+
				"	</p>\n" +
				"</div>\n";
	return str;
	}
	/**
	 * Game initialization code. The wrapper will be set at this point.
	 */
	public abstract void init();
	/**
	 * Paint the buffer
	 */
	public void paintComponent(Graphics g) {
		bufferGraphics.setColor(Color.BLACK);
		bufferGraphics.fillRect(0, 0, buffer.getWidth(), buffer.getHeight());
		draw(bufferGraphics);
		g.drawImage(buffer, 0, 0, getWidth(), getHeight(), 0, 0, buffer.getWidth(), buffer.getHeight(), null);
	}
	/**
	 * Called by the wrapper to start the game. This may not be called if only metadata is being read.
	 * Do not do anything until this is called.
	 */
	public void start(GameWrapper wrap) {
		wrapper = wrap;
		init();
		setFocusable(true);
		setPreferredSize(new Dimension(width(), height()));
		new java.util.Timer().scheduleAtFixedRate(new java.util.TimerTask(){
			public void run(){
				tick();
				repaint();
			}
		}, 1, 1000 / fps());
	}
	/**
	 * A short title for the game. This will be used for the distribution files. Make sure it does
	 * not include any illegal file characters!
	 * @return Short title
	 */
	public abstract String shortTitle();
	/**
	 * The events that should occur every frame.
	 */
	public abstract void tick();
	/**
	 * What is the title of the game
	 * @return The title of the game
	 */
	public abstract String title();
	/**
	 * What width is used to create the game? The default is 800. The buffer will be created with
	 * this width and it will be stretched on paint
	 * @return width of the game internals
	 */
	public int width() {
		return 800;
	}
}
